/*
 * Copyright (C) 2017 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the
 *       distribution.
 *    3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of
 *       its contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _EFPG_I_H_
#define _EFPG_I_H_

#include <stdlib.h>
#include <string.h>
#include "efpg/efpg.h"
#include "os.h"
#include "driver/chip/hal_uart.h"

#ifdef __cplusplus
extern "C" {
#endif

#define EFPG_KEY_LEN_MAX          (64)
#define EFPG_RECV_TIMEOUT_MS      (3000)
#define EFPG_THREAD_STACK_SIZE    (3 * 1024)

#define EFPG_CMD_FRAME_LEN        (8)
#define EFPG_ACK_FRAME_LEN        (4)
#define EFPG_MSG_DGST_LEN         (32)
#define EFPG_DATA_FRAME_LEN_MAX   ((76) + EFPG_MSG_DGST_LEN)

#define EFPG_HOSC_BUF_LEN         (1)
#define EFPG_HOSC_FRAME_LEN       (EFPG_HOSC_BUF_LEN  + EFPG_MSG_DGST_LEN)
#define EFPG_BOOT_BUF_LEN         (32)
#define EFPG_BOOT_FRAME_LEN       (EFPG_BOOT_BUF_LEN + EFPG_MSG_DGST_LEN)
#define EFPG_DCXO_BUF_LEN         (1)
#define EFPG_DCXO_FRAME_LEN       (EFPG_DCXO_BUF_LEN + EFPG_MSG_DGST_LEN)
#define EFPG_POUT_BUF_LEN         (3)
#define EFPG_POUT_FRAME_LEN       (EFPG_POUT_BUF_LEN  + EFPG_MSG_DGST_LEN)
#define EFPG_MAC_BUF_LEN          (6)
#define EFPG_MAC_FRAME_LEN        (EFPG_MAC_BUF_LEN  + EFPG_MSG_DGST_LEN)
#define EFPG_CHIPID_BUF_LEN       (16)
#define EFPG_CHIPID_FRAME_LEN     (EFPG_CHIPID_BUF_LEN + EFPG_MSG_DGST_LEN)
#if (CONFIG_CHIP_ARCH_VER == 3)
#define EFPG_SK_BUF_LEN           (16)
#define EFPG_SK_FRAME_LEN         (EFPG_SK_BUF_LEN + EFPG_MSG_DGST_LEN)
#define EFPG_SS_BUF_LEN           (1)
#define EFPG_SS_FRAME_LEN         (EFPG_SS_BUF_LEN + EFPG_MSG_DGST_LEN)
#endif

#define EFPG_OP_CODE_READ         (0x0FF0)
#define EFPG_OP_CODE_WRITE        (0xF00F)
#define EFPG_OP_CODE_EXIT         (0xFFFF)

#define EFPG_TYPE_HOSC            (0xFF00)
#define EFPG_TYPE_BOOT            (0xFE01)
#define EFPG_DCXO_TRIM            (0xFD02)
#define EFPG_POUT_CAL             (0xFC03)
#define EFPG_TYPE_MAC_WLAN        (0xFB04)
#define EFPG_TYPE_USER_AREA       (0xFA05)
#define EFPG_TYPE_CHIPID          (0xF906)
#if (CONFIG_CHIP_ARCH_VER == 3)
#define EFPG_POUT_CAL_BT          (0xF807)
#define EFPG_TYPE_MAC_BT          (0xF708)
#define EFPG_TYPE_SECRET_KEY      (0xF609)
#define EFPG_TYPE_SECURE_SWD      (0xF50A)
#endif

#define EFPG_NORMAL_CMD           (0)
#define EFPG_EXT_CMD              (1)
#define EFPG_UAER_AREA_EXT_LEN    (8 + (2 + 2) + 1)

#if (CONFIG_CHIP_ARCH_VER == 3)
#define EFPG_EFUSE_VER_START            (0)
#define EFPG_EFUSE_VER_NUM              (4)

#define EFPG_CHIPID_1ST_START           (128)
#define EFPG_CHIPID_1ST_NUM             (128)

#define EFPG_SECRETKEY_1ST_START        (256)
#define EFPG_SECRETKEY_1ST_NUM          (128)

#define EFPG_SECURE_SWD_START           (384)
#define EFPG_SECURE_SWD_NUM             (1)

#define EFPG_HOSC_TYPE_START            (385)
#define EFPG_HOSC_TYPE_NUM              (4)

#define EFPG_BOOT_FLAG_START            (389)
#define EFPG_BOOT_FLAG_NUM              (2)

#define EFPG_BOOT_1ST_EN_START          (391)
#define EFPG_BOOT_1ST_EN_NUM            (1)

#define EFPG_BOOT_1ST_NO_START          (392)
#define EFPG_BOOT_1ST_NO_NUM            (8)

#define EFPG_BOOT_2ND_EN_START          (400)
#define EFPG_BOOT_2ND_EN_NUM            (1)

#define EFPG_BOOT_2ND_NO_START          (401)
#define EFPG_BOOT_2ND_NO_NUM            (8)

#define EFPG_BOOT_HASH_START            (409)
#define EFPG_BOOT_HASH_NUM              (256)

#define EFPG_MAC_ADDRESS_FLAG_START     (665)
#define EFPG_MAC_ADDRESS_FLAG_NUM       (1)

#define EFPG_MAC_ADDRESS_START          (666)
#define EFPG_MAC_ADDRESS_NUM            (48)


#define EFPG_MAC_WLAN_ADDR_NUM          (0)

#define EFPG_MAC_WLAN_ADDR_FLAG_START   (EFPG_MAC_ADDRESS_START + EFPG_MAC_ADDRESS_NUM)//(714)
#define EFPG_MAC_WLAN_ADDR_FLAG_NUM     (EFPG_MAC_WLAN_ADDR_NUM)
#define EFPG_MAC_WLAN_ADDR_LEN          (48)
#if (EFPG_MAC_WLAN_ADDR_NUM >= 1)
#define EFPG_MAC_WLAN_ADDR1_START       (EFPG_MAC_WLAN_ADDR_FLAG_START + EFPG_MAC_WLAN_ADDR_FLAG_NUM)
#define EFPG_MAC_WLAN_ADDR1_NUM         (EFPG_MAC_WLAN_ADDR_LEN)
#endif
#if (EFPG_MAC_WLAN_ADDR_NUM >= 2)
#define EFPG_MAC_WLAN_ADDR2_START       (EFPG_MAC_WLAN_ADDR1_START + EFPG_MAC_WLAN_ADDR1_NUM)
#define EFPG_MAC_WLAN_ADDR2_NUM         (EFPG_MAC_WLAN_ADDR_LEN)
#endif
#if (EFPG_MAC_WLAN_ADDR_NUM >= 3)
#define EFPG_MAC_WLAN_ADDR3_START       (EFPG_MAC_WLAN_ADDR2_START + EFPG_MAC_WLAN_ADDR2_NUM)
#define EFPG_MAC_WLAN_ADDR3_NUM         (EFPG_MAC_WLAN_ADDR_LEN)
#endif
#if (EFPG_MAC_WLAN_ADDR_NUM >= 4)
#define EFPG_MAC_WLAN_ADDR4_START       (EFPG_MAC_WLAN_ADDR3_START + EFPG_MAC_WLAN_ADDR3_NUM)
#define EFPG_MAC_WLAN_ADDR4_NUM         (EFPG_MAC_WLAN_ADDR_LEN)
#endif
#if (EFPG_MAC_WLAN_ADDR_NUM >= 5)
#error EFPG_MAC_WLAN_ADDR_NUM should not be bigger than 4
#endif


#define EFPG_MAC_BT_ADDR_NUM            (1)

#define EFPG_MAC_BT_ADDR_FLAG_START     (EFPG_MAC_WLAN_ADDR_FLAG_START + (EFPG_MAC_WLAN_ADDR_NUM * (1 + EFPG_MAC_WLAN_ADDR_LEN)))
#define EFPG_MAC_BT_ADDR_FLAG_NUM       (EFPG_MAC_BT_ADDR_NUM)
#define EFPG_MAC_BT_ADDR_LEN            (48)
#if (EFPG_MAC_BT_ADDR_NUM >= 1)
#define EFPG_MAC_BT_ADDR1_START         (EFPG_MAC_BT_ADDR_FLAG_START + EFPG_MAC_BT_ADDR_FLAG_NUM)
#define EFPG_MAC_BT_ADDR1_NUM           (EFPG_MAC_BT_ADDR_LEN)
#endif
#if (EFPG_MAC_BT_ADDR_NUM >= 2)
#define EFPG_MAC_BT_ADDR2_START         (EFPG_MAC_BT_ADDR1_START + EFPG_MAC_BT_ADDR1_NUM)
#define EFPG_MAC_BT_ADDR2_NUM           (EFPG_MAC_BT_ADDR_LEN)
#endif
#if (EFPG_MAC_BT_ADDR_NUM >= 3)
#define EFPG_MAC_BT_ADDR3_START         (EFPG_MAC_BT_ADDR2_START + EFPG_MAC_BT_ADDR2_NUM)
#define EFPG_MAC_BT_ADDR3_NUM           (EFPG_MAC_BT_ADDR_LEN)
#endif
#if (EFPG_MAC_BT_ADDR_NUM >= 4)
#define EFPG_MAC_BT_ADDR4_START         (EFPG_MAC_BT_ADDR3_START + EFPG_MAC_BT_ADDR3_NUM)
#define EFPG_MAC_BT_ADDR4_NUM           (EFPG_MAC_BT_ADDR_LEN)
#endif
#if (EFPG_MAC_BT_ADDR_NUM >= 5)
#define EFPG_MAC_BT_ADDR5_START         (EFPG_MAC_BT_ADDR4_START + EFPG_MAC_BT_ADDR4_NUM)
#define EFPG_MAC_BT_ADDR5_NUM           (EFPG_MAC_BT_ADDR_LEN)
#endif
#if (EFPG_MAC_BT_ADDR_NUM >= 6)
#error EFPG_MAC_BT_ADDR_NUM should not be bigger than 5
#endif


#define EFPG_DCXO_TRIM_NUM              (1)

#define EFPG_DCXO_TRIM_FLAG_START       (EFPG_MAC_BT_ADDR_FLAG_START + (EFPG_MAC_BT_ADDR_NUM * (1 + EFPG_MAC_BT_ADDR_LEN)))
#define EFPG_DCXO_TRIM_FLAG_NUM         EFPG_DCXO_TRIM_NUM
#define EFPG_DCXO_TRIM_LEN              (8)
#if (EFPG_DCXO_TRIM_NUM >= 1)
#define EFPG_DCXO_TRIM1_START           (EFPG_DCXO_TRIM_FLAG_START + EFPG_DCXO_TRIM_FLAG_NUM)
#define EFPG_DCXO_TRIM1_NUM             (EFPG_DCXO_TRIM_LEN)
#endif
#if (EFPG_DCXO_TRIM_NUM >= 2)
#define EFPG_DCXO_TRIM2_START           (EFPG_DCXO_TRIM1_START + EFPG_DCXO_TRIM1_NUM)
#define EFPG_DCXO_TRIM2_NUM             (EFPG_DCXO_TRIM_LEN)
#endif
#if (EFPG_DCXO_TRIM_NUM >= 3)
#error EFPG_DCXO_TRIM_NUM should not be bigger than 2
#endif


#define EFPG_POUT_CAL_NUM               (1)

#define EFPG_POUT_CAL_FLAG_START        (EFPG_DCXO_TRIM_FLAG_START + (EFPG_DCXO_TRIM_NUM * (1 + EFPG_DCXO_TRIM_LEN)))
#define EFPG_POUT_CAL_FLAG_NUM          (EFPG_POUT_CAL_NUM)
#define EFPG_POUT_CAL_LEN               (21)
#if (EFPG_POUT_CAL_NUM >= 1)
#define EFPG_POUT_CAL1_START            (EFPG_POUT_CAL_FLAG_START + EFPG_POUT_CAL_FLAG_NUM)
#define EFPG_POUT_CAL1_NUM              (EFPG_POUT_CAL_LEN)
#endif
#if (EFPG_POUT_CAL_NUM >= 2)
#define EFPG_POUT_CAL2_START            (EFPG_POUT_CAL1_START + EFPG_POUT_CAL1_NUM)
#define EFPG_POUT_CAL2_NUM              (EFPG_POUT_CAL_LEN)
#endif
#if (EFPG_POUT_CAL_NUM >= 3)
#error EFPG_POUT_CAL_NUM should not be bigger than 2
#endif


#define EFPG_BT_POUT_CAL_NUM            (1)

#define EFPG_BT_POUT_CAL_FLAG_START     (EFPG_POUT_CAL_FLAG_START + (EFPG_POUT_CAL_NUM * (1 + EFPG_POUT_CAL_LEN)))
#define EFPG_BT_POUT_CAL_FLAG_NUM       (EFPG_BT_POUT_CAL_NUM)
#define EFPG_BT_POUT_CAL_LEN            (21)
#if (EFPG_BT_POUT_CAL_NUM >= 1)
#define EFPG_BT_POUT_CAL1_START         (EFPG_BT_POUT_CAL_FLAG_START + EFPG_BT_POUT_CAL_FLAG_NUM)
#define EFPG_BT_POUT_CAL1_NUM           (EFPG_BT_POUT_CAL_LEN)
#endif
#if (EFPG_BT_POUT_CAL_NUM >= 2)
#define EFPG_BT_POUT_CAL2_START         (EFPG_BT_POUT_CAL1_START + EFPG_BT_POUT_CAL1_NUM)
#define EFPG_BT_POUT_CAL2_NUM           (EFPG_BT_POUT_CAL_LEN)
#endif
#if (EFPG_BT_POUT_CAL_NUM >= 3)
#error EFPG_BT_POUT_CAL_NUM should not be bigger than 2
#endif

#define EFPG_ALL_BITS_START             (0)
#define EFPG_ALL_BITS_NUM               (1024)

#define EFPG_USER_AREA_START            (EFPG_BT_POUT_CAL_FLAG_START + (EFPG_BT_POUT_CAL_NUM * (1 + EFPG_BT_POUT_CAL_LEN)))
#define EFPG_USER_AREA_NUM              (EFPG_ALL_BITS_NUM - EFPG_USER_AREA_START)

#if (EFPG_USER_AREA_NUM < 0)
#error EFPG layout overflow !!!
#endif

#elif (CONFIG_CHIP_ARCH_VER == 2)

#define EFPG_CHIPID_1ST_START           (114)
#define EFPG_CHIPID_1ST_NUM             (128)

#define EFPG_HOSC_TYPE_START            (242)
#define EFPG_HOSC_TYPE_NUM              (4)

#define EFPG_BOOT_FLAG_START            (246)
#define EFPG_BOOT_FLAG_NUM              (2)

#define EFPG_BOOT_1ST_EN_START          (248)
#define EFPG_BOOT_1ST_EN_NUM            (1)

#define EFPG_BOOT_1ST_NO_START          (249)
#define EFPG_BOOT_1ST_NO_NUM            (8)

#define EFPG_BOOT_2ND_EN_START          (257)
#define EFPG_BOOT_2ND_EN_NUM            (1)

#define EFPG_BOOT_2ND_NO_START          (258)
#define EFPG_BOOT_2ND_NO_NUM            (8)

#define EFPG_BOOT_HASH_START            (266)
#define EFPG_BOOT_HASH_NUM              (256)

#define EFPG_DCXO_TRIM_FLAG_START       (522)
#define EFPG_DCXO_TRIM_FLAG_NUM         (3)

#define EFPG_DCXO_TRIM0_START           (50)
#define EFPG_DCXO_TRIM0_NUM             (8)

#define EFPG_DCXO_TRIM1_START           (525)
#define EFPG_DCXO_TRIM1_NUM             (8)

#define EFPG_DCXO_TRIM2_START           (533)
#define EFPG_DCXO_TRIM2_NUM             (8)

#define EFPG_DCXO_TRIM3_START           (541)
#define EFPG_DCXO_TRIM3_NUM             (8)

#define EFPG_POUT_CAL_FLAG_START        (549)
#define EFPG_POUT_CAL_FLAG_NUM          (3)

#define EFPG_POUT_CAL1_START            (552)
#define EFPG_POUT_CAL1_NUM              (21)

#define EFPG_POUT_CAL2_START            (573)
#define EFPG_POUT_CAL2_NUM              (21)

#define EFPG_POUT_CAL3_START            (594)
#define EFPG_POUT_CAL3_NUM              (21)

#define EFPG_MAC_FLAG_START             (615)
#define EFPG_MAC_FLAG_NUM               (6)

#define EFPG_MAC_ADDR_START             (621)
#define EFPG_MAC_ADDR_NUM               (48)

#define EFPG_MAC_ADDR2_START            (669)
#define EFPG_MAC_ADDR2_NUM              (48)

#define EFPG_MAC_ADDR3_START            (717)
#define EFPG_MAC_ADDR3_NUM              (48)

#define EFPG_USER_AREA_START            (765)
#define EFPG_USER_AREA_NUM              (259)
#endif

#define EFPG_DCXO_IDX_MAX               (3)
#define EFPG_POUT_IDX_MAX               (3)
#define EFPG_MAC_IDX_MAX                (9)

#define efpg_malloc(l)                  malloc(l)
#define efpg_free(p)                    free(p)
#define efpg_memcpy(d, s, n)            memcpy(d, s, n)
#define efpg_memset(s, c, n)            memset(s, c, n)
#define efpg_memcmp(s1, s2, n)          memcmp(s1, s2, n)

typedef enum efpg_op {
	EFPG_OP_READ        = 0,
	EFPG_OP_WRITE       = 1,
	EFPG_OP_EXIT        = 2,
	EFPG_OP_NUM         = 3,
} efpg_op_t;

typedef enum efpg_state {
	EFPG_STATE_CONTINUE = 0,
	EFPG_STATE_RESET    = 1,
	EFPG_STATE_STOP     = 2,
	EFPG_STATE_NUM      = 3,
} efpg_state_t;

typedef struct efpg_priv {
	UART_ID             uart_id;
	efpg_cb_t           start_cb;
	efpg_cb_t           stop_cb;

	uint8_t             key[EFPG_KEY_LEN_MAX];
	uint8_t             key_len;

	uint8_t             is_cmd;
	uint8_t             ext_cmd;
	uint8_t             cmd_frame[EFPG_CMD_FRAME_LEN];
	uint8_t             data_frame[EFPG_DATA_FRAME_LEN_MAX];
	uint8_t             ext_cmd_frame[EFPG_UAER_AREA_EXT_LEN];
	uint16_t            expt_len;
	uint16_t            recv_len;

	uint16_t            protocol_version;
	uint16_t            start_bit_addr;
	uint16_t            bit_length;

	efpg_op_t           op;
	efpg_field_t        field;
} efpg_priv_t;

efpg_state_t efpg_cmd_frame_process(efpg_priv_t *efpg);
efpg_state_t efpg_data_frame_process(efpg_priv_t *efpg);

uint16_t efpg_read_field(efpg_field_t field, uint8_t *data, uint16_t start_bit_addr, uint16_t bit_len);
uint16_t efpg_write_field(efpg_field_t field, uint8_t *data, uint16_t start_bit_addr, uint16_t bit_len);

#ifdef __cplusplus
}
#endif

#endif /* _EFPG_I_H_ */
